package config

import (
	"cloud_worm/util/uconfig"
	"fmt"
	"sync"
	"strings"
)

type MysqlConfig struct {
	UserName 	string		`json:"user_name"`
	Password 	string		`json:"password"`
	Host 		string		`json:"host"`
	Port 		string		`json:"port"`
	Database 	string		`json:"database"`
}

func (m *MysqlConfig) parse(container uconfig.ConfContainer) error {
	runMode := container.String("run_mode")
	if runMode == "" {
		return fmt.Errorf("no run_mode exist")
	}
	runModePrefix := runMode + "::"

	m.UserName = container.String(runModePrefix + "mysql.user_name")
	m.Password = container.String(runModePrefix + "mysql.password")
	m.Host = container.String(runModePrefix + "mysql.host")
	m.Port = container.String(runModePrefix + "mysql.port")
	m.Database = container.String(runModePrefix + "mysql.database")

	if m.UserName == "" || m.Password == "" || m.Host == "" || m.Port == "" || m.Database == "" {
		return fmt.Errorf("some database config error")
	}
	return nil
}


type ServerConfig struct {
	Domain 			string 		`json:"domain"`
	FilePort 		string		`json:"file_port"`
	FileBaseDir 	string		`json:"file_base_dir"`
	UploadIPs 		[]string	`json:"upload_ips"`
	
	WebPort 		string		`json:"web_port"`
}

func (s *ServerConfig) parse(container uconfig.ConfContainer) error {
	runMode := container.String("run_mode")
	if runMode == "" {
		return fmt.Errorf("no run_mode exist")
	}
	runModePrefix := runMode + "::"

	s.WebPort = container.String(runModePrefix + "server.web_port")

	s.FilePort = container.String(runModePrefix + "server.file_port")
	s.FileBaseDir = container.String(runModePrefix + "server.file_base_dir")
	uploadIPs := container.String(runModePrefix + "server.upload_ips")
	if s.WebPort == "" || s.FilePort == "" || s.FileBaseDir == "" || uploadIPs == "" {
		return fmt.Errorf("server config error")
	}
	s.Domain = container.String(runModePrefix + "server.domain")

	for _, ip := range strings.Split(uploadIPs, ",") {
		ip = strings.TrimSpace(ip)
		s.UploadIPs = append(s.UploadIPs, ip)
	}

	return nil
}

type GrayInfo struct {
	Version 		string 		`json:"version"`
	TargetType 		int 		`json:"target_type"`
	Target 			string		`json:"target"`
	TargetSet 		map[string]struct{}		`json:"target_set"`

	sync.RWMutex
}

func (g *GrayInfo) parse(container uconfig.ConfContainer) error {
	g.Lock()
	defer g.Unlock()

	runMode := container.String("run_mode")
	if runMode == "" {
		return fmt.Errorf("no run_mode exist")
	}
	runModePrefix := runMode + "::"

	g.Version = container.String(runModePrefix + "gray.version")
	g.Target = container.String(runModePrefix + "gray.target")
	var err error
	if g.TargetType, err = container.Int(runModePrefix + "gray.target_type"); err != nil {
		return err
	}

	g.TargetSet = make(map[string]struct{})
	for _, item := range strings.Split(g.Target, ",") {
		l := strings.TrimSpace(item)
		if len(l) <= 0 {
			continue
		}

		g.TargetSet[l] = struct{}{}
	}

	return nil
}

type LocalConfig struct {
	PprofEnable 	bool			`json:"pprof_enable"`
	PprofPort		string			`json:"pprof_port"`
}

func (l *LocalConfig) parse(container uconfig.ConfContainer) error {
	runMode := container.String("run_mode")
	if runMode == "" {
		return fmt.Errorf("no run_mode exist")
	}
	runModePrefix := runMode + "::"

	pprofFlag, err := container.Bool(runModePrefix + "local.pprof_enable")
	if err != nil {
		return err
	}
	l.PprofEnable = pprofFlag

	l.PprofPort = container.String(runModePrefix + "local.pprof_port")
	if l.PprofPort == "" {
		return fmt.Errorf("config 'local.pprof_port' error")
	}

	return nil
}

type TLSCertInfo struct {
	PemFile 		string			`json:"pem_file"`
	KeyFile 		string			`json:"key_file"`
}

func (t *TLSCertInfo) parse(container uconfig.ConfContainer) error {
	runMode := container.String("run_mode")
	if runMode == "" {
		return fmt.Errorf("no run_mode exist")
	}
	runModePrefix := runMode + "::"

	t.PemFile = container.String(runModePrefix + "tls.pem_file")
	t.KeyFile = container.String(runModePrefix + "tls.key_file")
	if (t.PemFile == "" && t.KeyFile == "") || (t.PemFile != "" && t.KeyFile != "") {
		// nothing
	} else {
		return fmt.Errorf("some tls config error")
	}

	return nil
}
